﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEditor;
using UnityEngine;
using System.Threading;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
[Serializable]
public class AssetRefrence
{
    //TD:
    //被引用的资源
    public List<AssetRefrence> beRenfrencedAssets;

    //引用的资源
    public List<string> RefrenceAssets;
    public string assetPath;


    public AssetRefrence()
    {
        RefrenceAssets = new List<string>();
    }
    public void DebugSelf()
    {

        Debug.Log("当前资源路径 : " + assetPath);
        Debug.Log("allRefCount : " + RefrenceAssets.Count);

        Debug.Log("<color=red>-----当前引用的资源-----</color>");
        foreach (var item in RefrenceAssets)
        {
            Debug.Log(item);
        }
        Debug.Log("<color=green>-----引用它的资源------</color>");
        foreach (var item in beRenfrencedAssets)
        {
            Debug.Log(item.assetPath);
        }
        Debug.Log("------------------------");
    }
}
[System.Serializable]
public class RefrenceMap
{
    public const string MapDataName = "RefrenceMap.bin";

    [System.NonSerialized]
    public string[][] refrencedGUID;
    [System.NonSerialized]
    public string[] assetPaths;

    public List<AssetRefrence> assetRefrence;

    public AssetRefrence QueryRefrence(string assetPath)
    {
        if (assetRefrence == null)
        {
            Debug.LogError("必须先构建资源引用查找表");
            return null;
        }
        assetPath = GetSimplifyPath(assetPath);
        AssetRefrence finded = null;
        foreach (var item in assetRefrence)
        {
            if (item != null && item.assetPath == assetPath)
            {
                finded = item;
                break;
            }
        }
        return finded;
    }
    public void BuildCache()
    {
        if (assetPaths == null || refrencedGUID == null)
        {
            Debug.LogError("必须先构建资源引用查找表");
            return;
        }
        assetRefrence = new List<AssetRefrence>();
        for (int i = 0; i < assetPaths.Length; i++)
        {
            string[] refPaths = refrencedGUID[i];
            if (refPaths != null && refPaths.Length > 0)
            {
                var refData = new AssetRefrence();
                refData.assetPath = GetSimplifyPath(assetPaths[i]);
                assetRefrence.Add(refData);
                for (int k = 0; k < refPaths.Length; k++)
                {
                    string refPath = AssetDatabase.GUIDToAssetPath(refPaths[k]);
                    refData.RefrenceAssets.Add(GetSimplifyPath(refPath));
                }
            }
        }
        
        if (assetRefrence.Count == 0)
        {
            return;
        }
        ParallelTask.BeginParallelTask(10);
        ParallelTask.DoParallelFor(assetRefrence.Count, (index) =>
         {
             assetRefrence[index].beRenfrencedAssets = new List<AssetRefrence>();
             for (int k = 0; k < assetRefrence.Count; k++)
             {
                 if (k == index)
                 {
                     continue;
                 }
                 if (assetRefrence[k].RefrenceAssets.Contains(assetRefrence[index].assetPath))
                 {
                     assetRefrence[index].beRenfrencedAssets.Add(assetRefrence[k]);
                 }
             }

         }, 16);
        ParallelTask.EndParallelTask();
    }
    public static string GetSimplifyPath(string fullPath)
    {
        if (string.IsNullOrEmpty(fullPath))
        {
            return string.Empty;
        }
        string result = fullPath;
        result = result.Replace(@"\", @"/");
        int index = result.IndexOf("Assets/");
        if (index != -1)
        {
            result = result.Substring(index + 7, result.Length - (index + 7));
        }
        return result;
    }
    public void SaveProjectRefrenceMap()
    {
        BuildCache();
        BinaryFormatter binFormat = new BinaryFormatter();
        Stream fStream = new FileStream(MapDataName, FileMode.Create, FileAccess.ReadWrite);
        binFormat.Serialize(fStream, this);
        fStream.Flush();
        fStream.Close();
    }

    private static RefrenceMap g_CacheMap = null;
    public static void CleanCache()
    {
        g_CacheMap = null;
    }
    public static RefrenceMap ReadFromProjectPathOrCache()
    {
        if (g_CacheMap != null)
        {
            return g_CacheMap;
        }
        if (!File.Exists(MapDataName))
        {
            Debug.LogError("本地不存在引用查找表! :" + MapDataName);
            return null;
        }
        BinaryFormatter binFormat = new BinaryFormatter();
        Stream fStream = new FileStream(MapDataName, FileMode.Open, FileAccess.Read);
        g_CacheMap = (RefrenceMap)binFormat.Deserialize(fStream);
        fStream.Flush();
        fStream.Close();
        return g_CacheMap;
    }
}

